#include "SPGameRoot.h"

using namespace SP;
using namespace SPG;

//-------------------------------------------------------------
// SPGState
//-------------------------------------------------------------
namespace
{

class SPGState
{
public:
	SPGState();
	double			m_fAbsoluteTime;
	double			m_fTime;
	float				m_fElapsedTime;
	float				m_fFPS;
	float				m_fConstantTimePerFrame;
	double			m_fLastStateUpdateTime;
	DWORD		m_dwLashtStateUpdateFrames;
	WCHAR		m_wcsFPSStats[64];
};

SPGState::SPGState()
{
	m_fAbsoluteTime = 0;
	m_fTime = 0;
	m_fElapsedTime = 0;
	m_fFPS = 0;
	m_fConstantTimePerFrame = 0;
	m_fLastStateUpdateTime = 0;
	m_dwLashtStateUpdateFrames = 0;
}

SPGState* SPGGetState()
{
	static SPGState staticState;
	return &staticState;
}

SPTimer* SPGGetGlobalTimer()
{
	static SPTimer timer;
	return &timer;
}

void SPGUpdateFrameStats()
{
	// Keep track of the frame count
	double fLastTime = SPGGetState()->m_fLastStateUpdateTime;
	DWORD dwFrames = SPGGetState()->m_dwLashtStateUpdateFrames;
	double fAbsTime = SPGGetState()->m_fAbsoluteTime;
	dwFrames++;
	SPGGetState()->m_dwLashtStateUpdateFrames = dwFrames;

	// Update the scene stats once per second
	if ( fAbsTime - fLastTime > 1.0f )
	{
		float fFPS = ( float )( dwFrames / ( fAbsTime - fLastTime ) );
		SPGGetState()->m_fFPS = fFPS;
		SPGGetState()->m_fAbsoluteTime = fAbsTime;
		SPGGetState()->m_fLastStateUpdateTime = 0;

		swprintf_s( SPGGetState()->m_wcsFPSStats, 64, L"%0.2f fps ", fFPS );
	}
}

}

//-------------------------------------------------------------
// SPGameRoot
//-------------------------------------------------------------
SPGameRoot* SPGGetRoot()
{
	static SPGameRoot staticGameRoot;
	return &staticGameRoot;
}

void SPGameRoot::Create( HWND hWnd, UINT width, UINT height )
{		
	m_hWnd = hWnd;
	SPD3D11RenderEnvironment* pRenderEnvironment;
	pRenderEnvironment = SPGetRenderEnvironment();
	pRenderEnvironment->Create( hWnd, width, height );
	
	SPG::GGetStatic();

	SPCamera* pCamera = new SPCamera();
	pCamera->SetWindow( width, height );
	SPGetRenderEnvironment()->SetCamera( pCamera );	
	
	m_pWorld = new GWorld();	
	m_pWorld->m_pInput = new SPInput( hWnd );
}

void SPGameRoot::SetWindow( UINT width, UINT height )
{
	if ( SPGetCamera() != NULL )
	{
		if ( SPGetCamera() )
			SPGetCamera()->SetWindow( width, height );
		SPGetCamera()->SetWindow( width, height );
	}
	SPGetRenderEnvironment()->SetWindow( width, height );

	m_nOldWidth = width;
	m_nOldHeight = height;
}

SPGameRoot::SPGameRoot()
{
	m_bPause = false;
	m_pWorld = NULL;

	m_bFrameFinished = true;
}

SPGameRoot::~SPGameRoot()
{

}

void SPGameRoot::OnFrame()
{
	m_bFrameFinished = false;
	if ( m_nOldHeight != m_nNewHeight || m_nOldHeight != m_nNewWidth )
	{
		SetWindow( m_nNewWidth, m_nNewHeight );
	}
	// UpdateFrameStats
	double fTime, fAbsTime; float fElapsedTime;
	SPGGetGlobalTimer()->GetTimeValues( &fTime, &fAbsTime, &fElapsedTime );

	if ( SPGGetState()->m_fConstantTimePerFrame )
	{
		fElapsedTime = SPGGetState()->m_fConstantTimePerFrame;
		fTime = SPGGetState()->m_fTime + fElapsedTime;
	}

	SPGGetState()->m_fTime = fTime;
	SPGGetState()->m_fElapsedTime = fElapsedTime;
	SPGGetState()->m_fAbsoluteTime = fAbsTime;

	SPGUpdateFrameStats();

	m_pWorld->m_pInput->Update();
	// Move all components 
	if ( !m_bPause )
	{
		m_pWorld->OnFrameMove( fElapsedTime );
	}

	// Clear
	SPGetRenderEnvironment()->Clear( XMFLOAT4( 0.2f, 0.1f, 0.15f, 1.0f ) );

	// Render
	m_pWorld->OnFrameRender();

	// Present
	SPGetRenderEnvironment()->Present();

	m_bFrameFinished = true;
}
